package iosr11.Service;

import iosr11.contact.dao.ContactsHelper;
import iosr11.data.Attendence;
import iosr11.data.Event;
import iosr11.data.EventSeries;
import iosr11.data.Group;
import iosr11.data.Mark;
import iosr11.data.ProjectGroup;
import iosr11.data.Student;
import iosr11.data.StudentEventSeries;
import iosr11.data.User;
import iosr11.data.UserGroup;
import iosr11.gbase.dao.AttendenceDAO;
import iosr11.gbase.dao.EventDAO;
import iosr11.gbase.dao.MarkDAO;
import iosr11.gbase.dao.ProjectGroupDAO;
import iosr11.gbase.dao.StudentDAO;
import iosr11.gbase.dao.StudentEventSeriesDAO;
import iosr11.gbase.dao.UserGroupDAO;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class StudentServiceImpl implements StudentService {

	private StudentDAO studentDAO;
	private StudentEventSeriesDAO studentEventSeriesDAO;
	//private EventSeriesDAO eventSeriesDAO;
	private UserGroupDAO userGroupDAO;
	private EventDAO eventDAO;
	private ContactsHelper contactsDAO;
	private MarkDAO markDAO;
	private AttendenceDAO attendenceDAO;
	private ProjectGroupDAO projectGroupDAO;
	private Logger log = Logger.getLogger("service-log");

	
	
	@Override
	public List<Student> getStudentsForProjectGroup(ProjectGroup group) {
		if (group==null){
			log.info("brak grupy projektowej");
			return null;
		}
		if (group.getId()==null){
			log.info("grupa nie posiada id");
			return null;
		}
		List<Student> lista = studentDAO.getByProjectGroup(group);
		if (lista==null){
			log.info("brak studentow do grupy");
			return null;
		}
		
		List<Student> result = new ArrayList<Student>();
		for (Student tmp : lista){
			Student stud = this.getStudentByID(tmp.getId());
			stud.setProjectGrp(group);
			result.add(stud);
		}
		SortResult.sortStudents(result);
		return result;
	}

	private List<Group> getStudentGroups(Student student){
		List <UserGroup> lista = userGroupDAO.getUserGroupForUser(student.getUser());
		if (lista==null){
			log.info("brak grup dla studenta");
			return null;
		}
		List<Group> result = new ArrayList<Group>();
		for (UserGroup ug : lista){
			Group tmp = contactsDAO.getGroupByRef(ug.getGroup().getId());
			if (tmp==null){
				log.info("blad w grupach studenta - przerwano");
				return null;
			}
			result.add(tmp);
		}
		log.info("znaleziono "+result.size()+" grup dla studenta");
		return result;
	}
		
	@Override
	public Class<Student> getServiceEntityClass() {
		return Student.class;
	}

	@Override
	public boolean createStudent(String name, String email, int indexNumber) {
		if ((name == null)||(email==null)||(indexNumber<1))
			return false;
		User user = new User(null, name, email);
		contactsDAO.addUser(user);
		Student student = new Student(user);
		student.setIndexNumber(indexNumber);
		return studentDAO.add(student);
	}

	@Override
	public boolean deleteStudent(Student student) {
		if (student==null){
			log.info("nie podano studenta");
			return false;
		}
		return this.deleteStudent(student.getEmail());
	}

	@Override
	public boolean deleteStudent(String email) {
		Student student = this.getStudent(email);
		if (student == null) {
			log.warning("Brak studenta o podanym emailu");
			return false;
		}
		List<Mark> marks = student.getGrades();
		List<Attendence> attendences = student.getAttendences();
		
		if (marks==null){
			markDAO.getStudentMarks(student);
		}
		if (marks!=null){
			log.info("usuwanie ocen studenta: "+student.getName());
			for (Mark tmp : marks){
				markDAO.delete(tmp);
			}
		}
		else {
			log.info("brak ocen studenta do usuniecia");
		}
		
		if (attendences==null){
			attendences = attendenceDAO.getStudentsAttendence(student);
		}
		if (attendences!=null){
			log.info("usuwanie obecnosci studenta");
			for (Attendence tmp : attendences){
				attendenceDAO.delete(tmp);
			}
		}
		else {
			log.info("brak obecnosci studenta do usuniecia");
		}
		
		if (!contactsDAO.deleteUser(student.getUser().getId())){
			log.info("nie usunieto kontaktu - brak podanego kontaktu");
			return false;
		}
		
		if  (!studentDAO.delete(student)){
			log.info("nie usunieto rekordu studenta w bazie");
			return false;
		}
		log.info("usunieto studenta z bazy i kontaktow");
		return  true;
	}

	@Override
	public boolean updateStudent(Student student) {
		if (!contactsDAO.updateUser(student.getUser())){
			log.warning("nie zmieniono danych w kontaktach");
			return false;
		}
		if (!studentDAO.update(student)){
			log.warning("nie zmieniono danych w bazie w rekordzie studenta");
			return false;
		}
		return true;
	}

	@Override
	public Student getStudent(String email) {
		/*zamiast emaila dziala tez nazwa studenta*/
		/*Pobranie danych usera (nazwisko, email, id w kontaktach)*/
		User user = new User();
		user = contactsDAO.getUser(email);
		if (user == null) return null;
		
		/*Pobranie dodatkowych danych dostepnych tylko przy studencie (numer indeksu, id w bazie)*/
		Student student =studentDAO.getByUserRef(user.getId());
		if (student==null) return null;
		student.setUser(user);
		
		/*pobranie ocen studenta*/
		student.setGrades(markDAO.getStudentMarks(student));

		/*pobranie obecnosci studenta*/
		student.setAttendences(attendenceDAO.getStudentsAttendence(student));
		
		/*pobieranie danych o grupach studenta*/
		List<Group> grupy = this.getStudentGroups(student);
		if (grupy==null){
			log.info("brak grup studenta - null");
		}
		else if (grupy.size()<1){
			log.info("brak grup studenta - size<1");
		}
		else {
			student.setGroups(grupy);
		}
		
		/*pobieranie grupy projektowej studenta*/
		if (student.getProjectGrp()!=null){
			log.info("wyszukiwanie grupy w bazie");
			if (student.getProjectGrp().getId()!=null){
				ProjectGroup pgroup = projectGroupDAO.getByID(student.getProjectGrp().getId());
				student.setProjectGrp(pgroup);
			}
		}
		else {
			log.info("brak referencji na grupe");
		}
		
		return student;
	}
	
	
	
	@Override
	public Student getStudentByID(String id) {
		if (id==null){
			log.info("brak id -przerwano");
			return null;
		}
		Student stud = studentDAO.getByID(id);
		if (stud==null){
			log.info("brak studenta o podanym id: "+id);
			return null;
		}
		if (stud.getUser()==null){
			log.info("brak usera dla studenta o podanym id");
			return null;
		}
		
		stud.setUser(contactsDAO.getUserByRef(stud.getUser().getId()));
		
		// oceny studenta
		List<Mark> tmp = markDAO.getStudentMarks(stud);
		stud.setGrades(tmp);
		
		// obecnosci studenta
		List<Attendence> tmpA = attendenceDAO.getStudentsAttendence(stud);
		stud.setAttendences(tmpA);
		
		if (stud.getProjectGrp()!=null){
			System.out.println(stud.getProjectGrp().getId());
			stud.setProjectGrp(projectGroupDAO.getByID(stud.getProjectGrp().getId()));
			System.out.println(stud.getProjectGrp().getGroupName());
		}
		
		// brak pobierania serii eventow
		/*if (stud.getProjectGrp()!=null){
			stud.setProjectGrp(projectGrp)
		}*/
		return stud;
	}

	@Override
	public List<Student> getStudentsForEvent(Event event) {
		if (event==null){
			log.warning("nie podano eventu");
			return null;
		}
		if (event.getSeries()==null){
			log.warning("brak serii - wyszukuje w bazie");
			Event tmp = eventDAO.getByID(event.getId());
			if (tmp.getSeries()==null){
				log.warning("brak danych o event serii - przerwano - rekord niekompletny");
				return null;
			}
			else {
				event.setSeries(tmp.getSeries());
			}
		}
		log.info("jest event seria dla eventu - wyszukuje studentow");
		return this.getStudentsForEventSeries(event.getSeries());
	}

	@Override
	public List<Student> getStudentsForEventSeries(EventSeries series) {
		List<StudentEventSeries> studseries = studentEventSeriesDAO.getStudentsForEventSeries(series);
		if (studseries==null){
			log.warning("brak studentow do event serii");
			return null;
		}
		List<Student> result = new ArrayList<Student>();
		for (StudentEventSeries tmp : studseries){
			if (tmp!=null){
				Student student = this.getStudentByID(tmp.getStudent().getId());
				result.add(student);
			}
		}
		SortResult.sortStudents(result);
		return result;
	}

	@Override
	public List<Student> getAllStudents() {
		List<Student> list = studentDAO.getAll();
		if (list == null) {
			log.warning("brak rekordow w bazie - brak studentow");
			return null;
		}
		List<Student> result = new ArrayList<Student>();
		int i=0;
		while(i<list.size()){
			/*
			 * dla kazdego studenta wypelniany jest objekt user 
			 * poprzez sekwencyjne ywolywania kontaktow
			 * i zwiekszane jesli dla danego rekordu mozna znalezc usera
			 * inaczej wpis jest usuwany z listy oraz i pozostaje bez zmian 
			 */
			Student student = list.get(i);
			Student tmp = this.getStudentByID(student.getId());
			if (tmp!=null)
				result.add(tmp);
			i++;
			
		}
		
		SortResult.sortAllStudents(result);
		return result;
	}

	// =================================================================
	// getery i settery uzywane do springa

	public StudentDAO getStudentDAO() {
		return studentDAO;
	}

	public void setStudentDAO(StudentDAO studentDAO) {
		this.studentDAO = studentDAO;
	}

	public ContactsHelper getContactsDAO() {
		return contactsDAO;
	}

	public void setContactsDAO(ContactsHelper contactsDAO) {
		this.contactsDAO = contactsDAO;
	}

	public MarkDAO getMarkDAO() {
		return markDAO;
	}

	public void setMarkDAO(MarkDAO markDAO) {
		this.markDAO = markDAO;
	}

	public void setAttendenceDAO(AttendenceDAO attendenceDAO) {
		this.attendenceDAO = attendenceDAO;
	}

	public void setStudentEventSeriesDAO(StudentEventSeriesDAO studentEventSeriesDAO) {
		this.studentEventSeriesDAO = studentEventSeriesDAO;
	}

	public void setEventDAO(EventDAO eventDAO) {
		this.eventDAO = eventDAO;
	}

	public void setUserGroupDAO(UserGroupDAO userGroupDAO) {
		this.userGroupDAO = userGroupDAO;
	}

	public void setProjectGroupDAO(ProjectGroupDAO projectGroupDAO) {
		this.projectGroupDAO = projectGroupDAO;
	}

}
